/**
  ******************************************************************************
  * @file    main.c
  * @author  AE Team
  * @version 1.0.3
  * @date    2024-05-28
  * @brief   本样例演示通过中断方式读取W25Q16的UID
  *          SPI帧的位宽为16比特
  *          需要在SPI1的中断服务程序中调用HAL_SPI_IRQHandler函数
  *
  * @note    硬件平台：SYM32L010_StartKit_V1.0
  *          接线说明：短接J17-J21, 短接J28
  *                    断开J14-J16
  *
  *          W25Q16芯片与MCU的接线如下所示
  *          NCS=PA02 / SCK=PA05 / MISO=PB05 / MOSI=PB06
  *
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2024 SIYIMicro.
  * All rights reserved.</center></h2>
  *
  *
  ******************************************************************************
  */


/******************************************************************************/
/* Include files                                                              */
/******************************************************************************/
#include "main.h"
#include "sym32l010_hal_sysctrl.h"
#include "sym32l010_hal_systick.h"
#include "sym32l010_hal_gpio.h"
#include "sym32l010_hal_spi.h"
#include "sym32l010_startkit_board.h"


/******************************************************************************/
/* Local pre-processor symbols/macros ('#define')                             */
/******************************************************************************/

/******************************************************************************/
/* Global variable definitions (declared in header file with 'extern')        */
/******************************************************************************/
SPI_HandleTypeDef hspi1;

/******************************************************************************/
/* Local type definitions ('typedef')                                         */
/******************************************************************************/

/******************************************************************************/
/* Local function prototypes ('static')                                       */
/******************************************************************************/
static void SPI_Init(void);

/******************************************************************************/
/* Local variable definitions ('static')                                      */
/******************************************************************************/

/******************************************************************************/
/* Local pre-processor symbols/macros ('#define')                             */
/******************************************************************************/

/******************************************************************************/
/* Function implementation - global ('extern') and local ('static')           */
/******************************************************************************/


/*******************************************************************************
 ** \brief  Main function of project
 **
 ** \return uint32_t return value, if needed
 **
 **
 ******************************************************************************/
int32_t main(void)
{
    uint32_t Count = 0;

    //------------------------------------------------------------
    // 读到W25Q16的UID
    uint16_t W25Cmd_ReadUid[7] = { 0x4B00 };
    uint16_t W25Data_UID[7];

    //------------------------------------------------------------
    // 配置HCLK = 48MHz
    HAL_SysCtrl_ConfigWaitCycle(48000000);
    HAL_SysCtrl_HSI_SetDiv(HSIOSC_TO_HSI48MHZ);

    // 初始化SysTick
    HAL_InitTick(48000000);

    // 初始化板载LED
    Bsp_Led_Init();

    // 初始化SPI
    SPI_Init();

    while (1)
    {
        //--------------------------------------------------------
        // Set Ncs = 0
        HAL_SPI_SSI_SETLOW(&hspi1);

        //--------------------------------------------------------
        // 增加Delay，为从机（MCU）预留处理时间10us
        FirmwareDelay(30);

        //--------------------------------------------------------
        // Send Cmd & Recv Uid
        HAL_SPI_TransmitReceive_IT(&hspi1, (uint8_t *)W25Cmd_ReadUid, (uint8_t *)W25Data_UID, 7);
        while (HAL_SPI_TransmitReceive_IT_IsComplete(&hspi1) == HAL_BUSY);
        if (HAL_SPI_TransmitReceive_IT_IsComplete(&hspi1) == HAL_ERROR)
        {
            while (1);
        }

        //--------------------------------------------------------
        // Set Ncs = 1
        HAL_SPI_SSI_SETHIGH(&hspi1);

        //--------------------------------------------------------
        if (Count++ > 100)
        {
            Count = 0;
            BSP_LED_TOG();
        }
        HAL_Delay(2);
    }
}


/*******************************************************************************
 * @brief  SPI初始化
 * @param  None
 * @retval None
 */
static void SPI_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    MemClr(&GPIO_InitStruct, sizeof(GPIO_InitStruct));

    HAL_SYSCTRL_GPIOA_CLK_ENABLE();
    HAL_SYSCTRL_GPIOB_CLK_ENABLE();
    HAL_SYSCTRL_SPI1_CLK_ENABLE();

    //------------------------------------------------------------
    // 配置 SPI 端口
    // NCS=PA02 / SCK=PA05 / MISO=PB05 / MOSI=PB06
    AFx_SPI1NCS_PA02();
    AFx_SPI1SCK_PA05();
    AFx_SPI1MISO_PB05();
    AFx_SPI1MOSI_PB06();

    GPIO_InitStruct.Pins = GPIO_PIN_2 | GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    HAL_GPIO_Init(SYM_GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pins = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    HAL_GPIO_Init(SYM_GPIOB, &GPIO_InitStruct);

    GPIO_InitStruct.Pins = GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULL_UP;
    HAL_GPIO_Init(SYM_GPIOB, &GPIO_InitStruct);

    //------------------------------------------------------------
    // 配置SPI
    MemClr(&hspi1, sizeof(hspi1));

    hspi1.Instance         = SYM_SPI1;
    hspi1.Init.WorkMode    = SPI_WORKMODE_MASTER;
    hspi1.Init.CommLines   = SPI_COMM2LINES_FullDuplex;
    hspi1.Init.DataWidth   = SPI_DATAWIDTH_16BIT;
    hspi1.Init.SckPolarity = SPI_SCKPOLARITY_NEGATIVE;
    hspi1.Init.SckPhase    = SPI_SCKPHASE_1EDGE;
    hspi1.Init.SckSource   = SPI_SCKSRC_PCLKDIV16;                    // SckFreq = 48/16= 3MHz
    hspi1.Init.FirstBit    = SPI_FIRSTBIT_MSB;
    hspi1.Init.NcsMode     = SPI_NCS_HARD_OUTPUT;
    HAL_SPI_Init(&hspi1);
    HAL_SPI_Enable(&hspi1);

    NVIC_ClearPendingIRQ(SPI1_IRQn);
    NVIC_EnableIRQ(SPI1_IRQn);
}


/*******************************************************************************
 ** EOF (not truncated)
 ******************************************************************************/
#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
    /* USER CODE BEGIN */
    /* User can add his own implementation to report the file name and line number,
       tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
    /* USER CODE END */
}
#endif /* USE_FULL_ASSERT */


/************************ (C) COPYRIGHT SIYIMicro *****END OF FILE*************/
